﻿
Imports std

Public Module configLoader
    Private Const listSeparator As String = character.comma
    Private WithEvents config As configMonitor = Nothing
    Private ReadOnly components As vector(Of pointer(Of Object)) = Nothing

    Sub New()
        components = New vector(Of pointer(Of Object))()
    End Sub

    Public Sub [stop]()
        stopComponents()
    End Sub

    Public Function load(ByVal configfile As String) As Boolean
        assert(config Is Nothing)
        config = New configMonitor()
        assert(config.open(configfile))
        Return load()
    End Function

    Private Function load() As Boolean
        assert(Not config Is Nothing)
        Return loadComponents()
    End Function

    Private Function loadComponent(ByVal name As String) As Boolean
        Dim s As String = Nothing
        If config.getparameter(name, "type", s) Then
            Dim c As Object = Nothing
            If generateComponent(name, s, c) Then
                Return components.push_back(New pointer(Of Object)(c))
            Else
                Return False
            End If
        Else
            Return False
        End If
    End Function

    Public Function generateComponent(ByVal section As String, ByVal t As String, ByRef c As Object) As Boolean
        If componentGenerator.generate(t, c) Then
            If componentInitializer.initial(t, section, config, c) Then
                Return True
            Else
                raiseError(errorHandle.errorType.user, "cannot initialize component ", section)
                Return False
            End If
        Else
            raiseError(errorHandle.errorType.user, "cannot create component ", t, " in ", section)
            Return False
        End If
    End Function

    Private Function stopComponents() As Boolean
        For i As Int64 = 0 To components.size() - 1
            If istype(Of iconsumer)(components(i).get()) Then
                convertor.cast(Of iconsumer)(components(i).get()).stop()
            ElseIf istype(Of iproducer)(components(i).get()) Then
                convertor.cast(Of iproducer)(components(i).get()).stop()
            Else
                Return False
            End If
        Next

        Return True
    End Function

    Private Function loadComponentsList(ByRef l As vector(Of String)) As Boolean
        Dim s As String = Nothing
        s = config.parameter("universe", "components", emptyString)
        If isemptystring(s) Then
            Return False
        Else
            strsepar(s, listSeparator, l, True)
            If l Is Nothing OrElse l.empty() Then
                Return False
            Else
                For i As Int64 = 0 To l.size() - 1
                    kickLeftRightBlank(l(i))
                Next
                Return True
            End If
        End If
    End Function

    Private Function loadComponents() As Boolean
        If stopComponents() Then
            Dim l As vector(Of String) = Nothing
            If loadComponentsList(l) Then
                For i As Int64 = 0 To l.size() - 1
                    If Not loadComponent(l(i)) Then
                        Return False
                    End If
                Next

                Return True
            Else
                Return False
            End If
        Else
            Return False
        End If
    End Function

    Private Sub config_configChanged() Handles config.configChanged
        If Not load() Then
            raiseError(errorHandle.errorType.user, "failed to reload config, ignore.")
        End If
    End Sub
End Module
